package cn.nr19.jian.token


import cn.nr19.jian.factory.NodeFactory

/**
 * 简对象属性,编辑器专用的。解析用 JianLeiApi
 * 这里没写 toStr ！
 * h19,23.10.20
 */
open class LeiNode : Node {

    var classObject : LeiNode?= null // 继承


    // 类信息
    var name = "" // 类名称 引用时则以别名为准

    // 泛型参数  一般用一个大写字母表示，在选择或设置该参数时，最好弹出大写字母表
    var dataTypePars : MutableList<String> ?= null
    // 泛型参数对应表  匹配EDataType
    val dataTypeForm : HashMap<String,String> = HashMap()
    fun setDataType(pos : Int,type : String){
        dataTypeForm[dataTypePars!![pos]] = type
    }
    /**
     * 转为数据类型时文本，如 键对值<T,K>
     */
    fun toDataTypeStr() : String{
        val strs = StringBuilder()
        strs.append(name)
        if (dataTypePars!=null && dataTypePars!!.size != 0){
            strs.append("<")
            dataTypePars!!.forEach {
                strs.append(it).append(",")
            }
            strs.delete(strs.length - 1,strs.length)
            strs.append(">")
        }
        return strs.toString()
    }

    /**
     * 创建空内容对象文本，如功能一样显示的啦！
     */
    fun toNewStr() : String{
        val strs = StringBuilder()
        strs.append(name)
        strs.append("(")
        pars.forEach {
            strs.append(it)
        }
        if (strs.endsWith(",")) strs.deleteCharAt(strs.length - 1)
        strs.append(")")
        return strs.toString()
    }


    //  class a<datatype>(pars) : classObject {}
    var pars = ArrayList<ParNode>() // 参数变量

    // 基本信息
    var vars = ArrayList<NVarNode>() // 变量
    var funs = ArrayList<NFunNode>() // 功能
    var events = ArrayList<NEventNode>() // 事件
    var imports = ArrayList<IMPORT>() // 引用




    constructor()
    constructor(str : String) : this(NodeFactory.start(str))
    constructor(stat : J2Node){
        val data = LeiNode()
        data.classObject = this.classObject
        stat.nodes.forEach {
            when(it){
                is NFunNode -> funs.add(it)
                is NVarNode -> vars.add(it)
                is IMPORT -> imports.add(it)
            }
        }
    }
    fun addPar(par : ParNode){
        this.pars.add(par)
    }
    fun addVar(obj : NVarNode){
        this.vars.add(obj)
    }
    fun addEvent(name : String){
        events.add(NEventNode().let {
            it.name = name
            it
        })
    }
    fun addEvent(event : NEventNode){
        events.add(event)
    }
    fun addFun(enFun : NFunNode){
        funs.add(enFun)
    }
    open fun getFuns() : List<NFunNode>{
        val ls = ArrayList<NFunNode>()
        ls.addAll(funs)
        classObject?.getFuns()?.apply {
            ls.addAll(this)
        }
        return ls
    }
    open fun getVars() : List<NVarNode>{
        val ls = ArrayList<NVarNode>()

        // 参数也属于变量
        pars.forEach {
            val eg = NVarNode()
            eg.type = it.type
            ls.add(eg)
        }
        ls.addAll(vars)
        classObject?.getVars()?.apply {
            ls.addAll(this)
        }
        return ls
    }
    fun getEvent() : List<NEventNode>{
        val maps = ArrayList<NEventNode>()

        // 优先本级
        maps.addAll(events)

        classObject?.getEvent()?.apply {
            maps.addAll(this)
        }

        return maps
    }
    fun addImport(obj : IMPORT){
        imports.add(obj)
    }
    fun addImports(objs : List<IMPORT>){
        imports.addAll(objs)
    }
    fun getImports() : List<IMPORT>{
        val ls = ArrayList<IMPORT>()
        ls.addAll(imports)
        classObject?.getImports()?.apply {
            ls.addAll(this)
        }
        return ls
    }


    /**
     * 基于本数据（本数据归为父类），创建一个新类并返回
     */
    fun newJianData(stat : J2Node) : LeiNode {
        val data = LeiNode()
        data.classObject = this
        stat.nodes.forEach {
            when(it){
                is NFunNode -> data.funs.add(it)
                is NVarNode -> data.vars.add(it)
                is IMPORT -> data.imports.add(it)
            }
        }
        return data
    }

    /**
     * 重置数据
     */
    fun reData(stat : J2Node) : LeiNode {
        reData()
        stat.nodes.forEach {
            when(it){
                is NFunNode -> funs.add(it)
                is NVarNode -> vars.add(it)
                is IMPORT -> imports.add(it)
            }
        }
        return this
    }
    fun reData() : LeiNode {
        funs.clear()
        vars.clear()
        imports.clear()
        return this
    }

    override fun toStr(level: Int, tabStr: String): String {
        return ""
    }

    override fun nodeType(): ENode = ENode.value





}